package ${t.packagePath}.controller;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import com.ejlchina.okhttps.OkHttps;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.bitwalker.useragentutils.UserAgent;
import cn.dev33.satoken.spring.SpringMVCUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import ${t.packagePath}.service.${t.userTableName}LoginService;
import ${t.packagePath}.service.${t.userRoleTableName}Service;
import ${t.packagePath}.service.${t.cfgTableName}Service;
import ${t.packagePath}.model.${t.userTableName}Login;
import ${t.packagePath}.model.${t.userTableName};
import ${t.packagePath}.model.${t.userRoleTableName};
import ${t.packagePath}.model.${t.cfgTableName};

import ${t.packagePath}.utils.AjaxJson;
import ${t.packagePath}.config.StpSpUserUtil;
import ${t.packagePath}.config.StpInterfaceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import lombok.AllArgsConstructor;
import java.lang.reflect.Method;
import cn.hutool.core.util.ReflectUtil;
import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.SearchResult;
import cn.zhxu.bs.util.MapUtils;
import javax.servlet.http.HttpServletRequest;
import io.swagger.annotations.ApiOperation;
import ${t.packagePath}.service.${t.userTableName}Service;
import ${t.packagePath}.model.${t.userTableName};
<#if cfg.saTokenAuthWay == 1 >import cn.dev33.satoken.stp.StpUtil;
<#else>import cn.dev33.satoken.annotation.SaCheckPermission;
</#if>


/**
 * Controller: ${t.tableName} -- ${t.tableComment}
 * @author ${cfg.author} 
 */
@RestController
@AllArgsConstructor(onConstructor_ = {@Autowired})
public class ${t.userTableName}Controller {

	/**
     * 密码的MD5盐值
     */
    private static final String MD5_SALT = "CS";
    StpInterfaceImpl stpInterface;
	${t.userTableName}LoginService ${t.userTableName?uncap_first}LoginService;
    ${t.userRoleTableName}Service ${t.userRoleTableName?uncap_first}Service;
    ${t.cfgTableName}Service ${t.cfgTableName?uncap_first}Service;
	${t.userTableName}Service ${t.userTableName?uncap_first}Service;
	BeanSearcher searcher;

	@ApiOperation("增")
	@${cfg.apiMappingWayString}("/admin/add")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
	@Transactional(rollbackFor = Exception.class)
	public AjaxJson add(${t.userTableName} ${t.userTableName?uncap_first}){
<#if cfg.saTokenAuthWay == 1 >        StpUtil.checkPermission(${t.modelName}.PERMISSION_CODE);${cfg.line}</#if><#rt>
		boolean b = ${t.userTableName?uncap_first}Service.save(${t.userTableName?uncap_first});
		String md5Password = SecureUtil.md5(MD5_SALT + ${t.userTableName?uncap_first}.getId() + ${t.userTableName?uncap_first}.getPassword()).toUpperCase();
		${t.userTableName?uncap_first}.setPw(${t.userTableName?uncap_first}.getPassword());
		${t.userTableName?uncap_first}.setPassword(md5Password);
		${t.userTableName?uncap_first}Service.updateById(${t.userTableName?uncap_first});
		return AjaxJson.getSuccessData(b);
	}

	@ApiOperation("删")
	@${cfg.apiMappingWayString}("/admin/delete")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
	public AjaxJson delete(${t.primaryKey.fieldType} id){
<#if cfg.saTokenAuthWay == 1 >        StpUtil.checkPermission(${t.userTableName}.PERMISSION_CODE);${cfg.line}</#if><#rt>

		// 不能自己删除自己
        if (Stp${t.userTableName}Util.getLoginIdAsLong() == id) {
            return AjaxJson.getError("不能自己删除自己");
        }
		boolean b = ${t.userTableName?uncap_first}Service.removeById(id);
		return AjaxJson.getByBoolean(b);
	}
	
	@ApiOperation("删-批量")
	@${cfg.apiMappingWayString}("/admin/deleteByIds")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
	public AjaxJson deleteByIds(HttpServletRequest request){
<#if cfg.saTokenAuthWay == 1 >        StpUtil.checkPermission(${t.userTableName}.PERMISSION_CODE);${cfg.line}</#if><#rt>
<#if t.hasFo("logic-delete")>
		int line = ${t.varName}Service.updateColumnByIds(${t.userTableName}.TABLE_NAME, "${t.getDbColumnByFoType('logic-delete').columnName}", ${t.getDbColumnByFoType('logic-delete').tx.no}, ids);
<#else>
		Map<String, Object> flat = MapUtils.flat(request.getParameterMap());
        Object object = flat.get("ids");
        if (object == null) {
            return AjaxJson.getSuccess();
        }
        List<Long> ids = Arrays.stream(object.toString().split(",")).map(Long::parseLong).collect(Collectors.toList());
        if (ids.contains(Stp${t.userTableName}Util.getLoginIdAsLong())) {
            return AjaxJson.getError("不能自己删除自己");
        }
		boolean b =${t.userTableName?uncap_first}Service.removeByIds(ids);
</#if>
		return AjaxJson.getByBoolean(b);
	}

	@ApiOperation("改")
	@${cfg.apiMappingWayString}("/admin/update")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
	public AjaxJson update(${t.userTableName} ${t.userTableName?uncap_first}){
<#if cfg.saTokenAuthWay == 1 >        StpUtil.checkPermission(${t.userTableName}.PERMISSION_CODE);${cfg.line}</#if><#rt>

		String md5Password = SecureUtil.md5(MD5_SALT + ${t.userTableName?uncap_first}.getId() + ${t.userTableName?uncap_first}.getPassword()).toUpperCase();
		${t.userTableName?uncap_first}.setPw(${t.userTableName?uncap_first}.getPassword());
		${t.userTableName?uncap_first}.setPassword(md5Password);
		boolean b =${t.userTableName?uncap_first}Service.updateById(${t.userTableName?uncap_first});
		return AjaxJson.getByBoolean(b);
	}

	/**
     * 改密码
     */
    @RequestMapping("/admin/updatePassword")
    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)
    public AjaxJson updatePassword(long id, String password) {
		${t.userTableName} byId = ${t.userTableName?uncap_first}Service.getById(id);
        String md5Password = SecureUtil.md5(MD5_SALT + byId.getId() + password).toUpperCase();
        byId.setPassword(md5Password);
        byId.setPw(password);
        boolean b = ${t.userTableName?uncap_first}Service.updateById(byId);
        return AjaxJson.getByBoolean(b);
    }
	/**
     * 改头像
     */
    @RequestMapping("/admin/updateAvatar")
    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)
    public AjaxJson updateAvatar(long id, String avatar) {
        SpUser byId = spUserService.getById(id);
        byId.setAvatar(avatar);
        boolean b = ${t.userTableName?uncap_first}Service.updateById(byId);
        return AjaxJson.getByBoolean(b);
    }

	/**
     * 改状态
     */
    @RequestMapping("/admin/updateStatus")
    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)
    public AjaxJson updateStatus(long id, int status) {

        // 验证对方是否为超管
        if (Stp${t.userTableName}Util.hasPermission(id, "administrator")) {
            return AjaxJson.getError("抱歉，对方角色为最高权限，您暂时无法完成此操作");
        }

        SpUser byId = ${t.userTableName?uncap_first}Service.getById(id);
        byId.setStatus(status);
        boolean b = ${t.userTableName?uncap_first}Service.updateById(byId);

        // 如果是禁用，就将其强制注销
        if (status == 2) {
            Stp${t.userTableName}Util.logout(id);
        }
        return AjaxJson.getByBoolean(b);
    }


	/**
     * 改角色
     */
    @RequestMapping("/admin/updateRole")
    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)
    @Transactional(rollbackFor = Exception.class)
    public AjaxJson updateRole(long id, String roleIds) {
        ${t.userRoleTableName?uncap_first}Service.remove(new LambdaQueryWrapper<${t.userRoleTableName}>().eq(${t.userRoleTableName}::getUserId, id));
        if (StrUtil.isBlank(roleIds)) {
            return AjaxJson.getSuccess();
        }
        for (String roleId : roleIds.split(",")) {
            ${t.userRoleTableName} ${t.userRoleTableName?uncap_first} = new ${t.userRoleTableName}();
            ${t.userRoleTableName?uncap_first}.setUserId(id);
            ${t.userRoleTableName?uncap_first}.setRoleId(Long.parseLong(roleId));
            ${t.userRoleTableName?uncap_first}Service.save(${t.userRoleTableName?uncap_first});
        }
        // 返回
        return AjaxJson.getSuccess();
    }


	@ApiOperation("查")
	@${cfg.apiMappingWayString}("/admin/getById")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
		public AjaxJson getById(${t.primaryKey.fieldType} id){
		${t.userTableName} ${t.userTableName?uncap_first} = ${t.userTableName?uncap_first}Service.getById(id);
		return AjaxJson.getSuccessData(${t.userTableName?uncap_first});
	}

	/**
     * 返回当前 Admin 信息
     */
    @RequestMapping("/admin/getByCurr")
    AjaxJson getByCurr() {
        long currentUserId = Stp${t.userTableName}Util.getLoginIdAsLong();
		${t.userTableName} ${t.userTableName?uncap_first} = ${t.userTableName?uncap_first}Service.getById(currentUserId);
        return AjaxJson.getSuccessData(${t.userTableName?uncap_first});
    }

	/** 查集合 - 根据条件（参数为空时代表忽略指定条件） */
	@${cfg.apiMappingWayString}("/admin/getList")
<#if cfg.saTokenAuthWay == 2 >    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)${cfg.line}</#if><#rt>
	public AjaxJson getList(HttpServletRequest request) {
		SearchResult<${t.userTableName}> search = searcher.search(${t.userTableName}.class, MapUtils.flat(request.getParameterMap()));
    	return AjaxJson.getPageData(search.getTotalCount().longValue(), search.getDataList());
	}

	/**
     * 当前 Admin 修改自己信息
     */
    @RequestMapping("/admin/updateInfo")
    public AjaxJson updateInfo(${t.userTableName} obj) {
        obj.setId(Stp${t.userTableName}Util.getLoginIdAsLong());
        boolean b = ${t.userTableName?uncap_first}Service.updateById(obj);
        return AjaxJson.getByBoolean(b);
    }
	/**
     * 模拟指定账号登录
     */
    @RequestMapping("/admin/runAs")
    @SaCheckPermission(type= Stp${t.userTableName}Util.TYPE,value=${t.userTableName}.PERMISSION_CODE)
    public AjaxJson runAs(long adminId) {
        // 如果不存在这个账号
        if (${t.userTableName?uncap_first}Service.getById(adminId) == null) {
            return AjaxJson.getError("未找到账号：" + adminId);
        }
        // 如果要模拟的账号就是当前账号
        if (Stp${t.userTableName}Util.getLoginIdAsLong() == adminId) {
            return AjaxJson.getError("不能自己模拟自己");
        }

        // 获取这个人的token
        String token = Stp${t.userTableName}Util.createLoginSession(adminId);
        return AjaxJson.getSuccessData(token);
    }
	/**
     * 账号、密码登录
     */
    @RequestMapping("/AccAdmin/doLogin")
    @Transactional(rollbackFor = Exception.class)
    public AjaxJson doLogin(String key, String password) {
        // 1、验证参数
        if (!StrUtil.isAllNotBlank(key, password)) {
            return AjaxJson.getError("请提供key与password参数");
        }
		${t.userTableName} ${t.userTableName?uncap_first} = ${t.userTableName?uncap_first}Service.lambdaQuery().eq(${t.userTableName}::getPhone, key).one();
        if (${t.userTableName?uncap_first} == null) {
            return AjaxJson.getError("账号不存在");
        }
        if (!${t.userTableName?uncap_first}.getPassword().equals(SecureUtil.md5(MD5_SALT + ${t.userTableName?uncap_first}.getId() + password).toUpperCase())) {
            return AjaxJson.getError("密码错误");
        }
        if (${t.userTableName?uncap_first}.getStatus() == 2) {
            return AjaxJson.getError("此账号已被禁用，如有疑问，请联系管理员");
        }
        // =========== 至此, 已登录成功 ============
        Stp${t.userTableName}Util.login(${t.userTableName?uncap_first}.getId());
        String tokenValue = Stp${t.userTableName}Util.getTokenValue();
        //添加日志
        HttpServletRequest request = SpringMVCUtil.getRequest();
        UserAgent ua = UserAgent.parseUserAgentString(request.getHeader("user-agent"));

        String ip = request.getHeader("x-forwarded-for");
        ip = checkIp(ip) ? ip : (
                checkIp(ip = request.getHeader("Proxy-Client-IP")) ? ip : (
                        checkIp(ip = request.getHeader("WL-Proxy-Client-IP")) ? ip :
                                request.getRemoteAddr()));
        String loginIp = ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;


        // 1、修改 admin表 最后登录日志
		${t.userTableName?uncap_first}.setLoginIp(loginIp);
        ${t.userTableName?uncap_first}.setLoginTime(new Date());
        ${t.userTableName?uncap_first}.setLoginCount(spUser.getLoginCount() + 1);

        ${t.userTableName?uncap_first}Service.updateById(spUser);
        // 2、在管理员登录日志表增加记录
		${t.userTableName}Login al = new ${t.userTableName}Login();
        al.setAccId(${t.userTableName?uncap_first}.getId());
        al.setAccToken(tokenValue);
        al.setLoginIp(loginIp);
        al.setAddress(getAddres(loginIp));
        al.setDevice(ua.getBrowser().getName());
        al.setSys(ua.getOperatingSystem().getName());
        al.setCreateTime(new Date());
		${t.userTableName?uncap_first}LoginService.save(al);
        // 组织返回参数
        HashMap<String, Object> map = new HashMap<>();
        map.put("admin", ${t.userTableName?uncap_first});
        ${t.cfgTableName} ${t.cfgTableName?uncap_first} = ${t.cfgTableName?uncap_first}Service.lambdaQuery().eq(${t.cfgTableName}::getCfgName, "app_cfg").one();
        map.put("appCfg", ${t.cfgTableName?uncap_first} == null ? null : ${t.cfgTableName?uncap_first}.cfgValue);
        //所有的权限码List<String>
    	map.put("perList", stpInterface.getPermissionList(${t.userTableName?uncap_first}.getId(),Stp${t.userTableName}Util.TYPE));
        //菜单
        map.put("menuList", stpInterface.getMenuList(${t.userTableName?uncap_first}.getId(),Stp${t.userTableName}Util.TYPE));
        map.put("tokenInfo", Stp${t.userTableName}Util.getTokenInfo());
        return AjaxJson.getSuccessData(map);
        }
        private boolean checkIp(String ip) {
        return StrUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip);
        }

        public static String getAddres(String ip) {
        try {
        // 如果是127.0.0.1
        if (ip.equals("127.0.0.1")) {
        return "unknown";
        }

        // 请求
        String url = "http://whois.pconline.com.cn/ipJson.jsp"
        + "?json=true"
        + "&ip=" + ip;
        String body = OkHttps.sync(url).get().getBody().toString();
        Map map = new ObjectMapper().readValue(body, Map.class);
        String addr = map.get("addr") != null ? map.get("addr") + "" : null;

        // 如果是局域网，则返回 unknown
        if (addr == null || addr.contains("本机地址") || addr.contains("局域网")) {
        return "unknown";
        }

        // 正常返回
        return addr;
        } catch (Exception e) {
        e.printStackTrace();
        return "unknown";
        }
    }

    /**
    * 退出登录
    */
    @RequestMapping("/AccAdmin/doExit")
    public AjaxJson doExit() {
        Stp${t.userTableName}Util.logout();
        return AjaxJson.getSuccess();
    }

    /**
    * 获取会话信息
    *
    * @throws InterruptedException
    */
    @RequestMapping("/AccAdmin/getLoginInfo")
    public AjaxJson getLoginInfo() {

        // 当前admin
        long adminId = Stp${t.userTableName}Util.getLoginIdAsLong();
        ${t.userTableName} ${t.userTableName?uncap_first} = ${t.userTableName?uncap_first}Service.getById(adminId);

        // 组织参数 (admin信息，权限信息，配置信息)
        HashMap<String, Object> map = new HashMap<>();
        map.put("admin", ${t.userTableName?uncap_first});

        //所有的权限码List<String>
        map.put("perList", stpInterface.getPermissionList(${t.userTableName?uncap_first}.getId(),Stp${t.userTableName}Util.TYPE));
        //菜单
        map.put("menuList", stpInterface.getMenuList(${t.userTableName?uncap_first}.getId(),Stp${t.userTableName}Util.TYPE));
        SpCfg appCfg = spCfgService.lambdaQuery().eq(SpCfg::getCfgName, "app_cfg").one();
        map.put("appCfg", appCfg == null ? null : appCfg.cfgValue);
        return AjaxJson.getSuccessData(map);
    }
    /**
    * 指定用户修改自己密码
    */
    @RequestMapping("/AdminPassword/update")
    public AjaxJson updatePassword(String oldPwd, String newPwd) {
        // 1、转md5
        long adminId = Stp${t.userTableName}Util.getLoginIdAsLong();
        ${t.userTableName} ${t.userTableName?uncap_first} = ${t.userTableName?uncap_first}Service.getById(adminId);
        String oldPwdMd5 = SecureUtil.md5(MD5_SALT + ${t.userTableName?uncap_first}.getId() + oldPwd).toUpperCase();

        // 2、验证
        if (!oldPwdMd5.equals(${t.userTableName?uncap_first}.getPassword())) {
        return AjaxJson.getError("旧密码输入错误");
        }

        // 3、开始改
        spUser.setPassword(SecureUtil.md5(MD5_SALT + ${t.userTableName?uncap_first}.getId() + newPwd).toUpperCase());
        boolean b = ${t.userTableName?uncap_first}Service.updateById(${t.userTableName?uncap_first});
        return AjaxJson.getByBoolean(b);
    }
}
